package com.gtamos.dicebot.gambling;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;

import javax.json.JsonNumber;
import javax.json.JsonObject;

import com.gtamos.dicebot.constants.DiceBotConstants;
import com.gtamos.dicebot.gambling.game.AbstractGambling;
import com.gtamos.dicebot.interfaces.Runner;
import com.gtamos.dicebot.printers.ConsolePrinter;

import dice.client.web.BeginSessionResponse;
import dice.client.web.DiceResponse;
import dice.client.web.DiceWebAPI;
import dice.client.web.SessionInfo;

public class GameRunner implements Runner{

	@Override
	public void play(String apiKey, String user, String password, AbstractGambling gamblingGameType) {

		Integer maxBets = DiceBotConstants.MAX_BETS;
		BeginSessionResponse beginSessionResponse = DiceWebAPI.BeginSession(apiKey, user, password);
		SessionInfo session = beginSessionResponse.getSession();
		BigDecimal initialBalance = session.getBalance();
		BigDecimal initialBetBalance = initialBalance;
		ConsolePrinter.printInitialization(gamblingGameType);
		BigDecimal initialBet;
		for (Integer j = 0 ; j < DiceBotConstants.BETS_CYCLES ; j++){
			beginSessionResponse = DiceWebAPI.BeginSession(apiKey, user, password);
			session = beginSessionResponse.getSession();
			ConsolePrinter.printOnCycleStartInfo(j, initialBalance);
			Integer win = 0;
			Integer loss = 0;
			Integer maxConsecutiveWins = 0;
			Integer consecutiveWins = 0;
			Integer maxConsecutiveLoss = 0;
			Integer consecutiveLoss = 0;


			BigDecimal newBalance = initialBalance;

			String betType = "Bet# ";
			Integer i;
			Date d0 = new Date();
			initialBet = newBalance.multiply(gamblingGameType.getBET_INVERSION_PERCENT());
			initialBet = DiceWebAPI.TruncateSatoshis(initialBet);
			BigDecimal payIn = initialBet;
			BigDecimal maxBet = payIn;
			for(i = 0; i<maxBets ; i++){
				Date d1 = new Date();
				if(payIn.compareTo(newBalance) > 0){
					payIn = newBalance;
				}
				DiceResponse response;
				response = DiceWebAPI.PlaceBet(session, payIn, gamblingGameType.getGUESS_LOW(), gamblingGameType.getGUESS_HIGH());
				Boolean success = response.isSuccess();
				ConsolePrinter.printPlacedBetStatus(success);
				if(!success){
					System.exit(0);
				}
				Date d2 = new Date();
				newBalance = session.getBalance();			

				ConsolePrinter.printBetInfo(d1, d2, betType, i, payIn);
				JsonObject jsonObject = response.getRawResponse();
				BigDecimal secret = ((JsonNumber) jsonObject.get("Secret")).bigDecimalValue();
				Boolean losseGambling = gamblingGameType.getGUESS_HIGH().compareTo(secret.longValue()) < 0; 
				ConsolePrinter.printBalanceInfo(losseGambling, initialBetBalance, newBalance, secret);
				if(losseGambling && success){
					consecutiveLoss ++;
					payIn = payIn.multiply(gamblingGameType.getBET_MULTIPLIER()).add(newBalance.multiply(gamblingGameType.getEXTRA_SATOSHIS_MULTIPLIER()));	

					payIn = DiceWebAPI.TruncateSatoshis(payIn);
					loss++;
					consecutiveWins = 0;
					if(consecutiveLoss > maxConsecutiveLoss){
						maxConsecutiveLoss = consecutiveLoss;
					}
					if(consecutiveLoss == 3){
						payIn = newBalance;
					}
					if(i + 1  == maxBets){
						maxBets += 1;
						betType = "(extra) Bet# ";
					}
					if(payIn.compareTo(maxBet) > 0){
						maxBet = payIn;
					}

				}else if(success){
					payIn = initialBet;
					win++;
					consecutiveWins++;
					consecutiveLoss = 0;
					if(consecutiveWins > maxConsecutiveWins){
						maxConsecutiveWins = consecutiveWins;
					}
				}				
				initialBetBalance = newBalance;				
			}
			newBalance = session.getBalance();
			ConsolePrinter.printCycleResume(i, d0, initialBalance, newBalance, maxBet, consecutiveWins, maxConsecutiveWins, consecutiveLoss, maxConsecutiveLoss);
			payIn = initialBet;
			initialBalance = newBalance;
			maxBets = DiceBotConstants.MAX_BETS;			
		}



	}

}
